package com.zyy.jomap;

import com.zyy.jomap.definition.JoMapDefinition;
import com.zyy.jomap.constant.Constant;
import com.zyy.jomap.util.CollectUtil;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * JoMap工具方法
 * @author zhangyy
 */
public class JoMapper {

    private static Map<String, JoMapBase> convertClazzNameKeyJoBaseMap=new HashMap<>();

    /**
     * 单个实例属性赋值
     * @param sourceObj
     * @param targetClazz
     * @param <T>
     * @return
     */
    public static <T> T copyBean(Object sourceObj,Class<T> targetClazz){
        String sourceClazzName=sourceObj.getClass().getSimpleName();
        String targetClazzName=targetClazz.getSimpleName();
        String convertClazzName=sourceClazzName.concat(Constant.CONVERT_JO_CHAR).concat(targetClazzName);
        String convertReverseClazzName=targetClazzName.concat(Constant.CONVERT_JO_CHAR).concat(sourceClazzName);
        JoMapBase joMapBase =convertClazzNameKeyJoBaseMap.get(convertClazzName);
        if(joMapBase!=null){
            return (T) joMapBase.copyBean(sourceObj);
        }
        //反转
        joMapBase=convertClazzNameKeyJoBaseMap.get(convertReverseClazzName);
        if(joMapBase!=null){
            return  (T) joMapBase.copyBeanReverse(sourceObj);
        }else{
            //缓存中不存在 加载并存入缓存
            JoMapDefinition joMapDefinition=parseConvertInstant(sourceObj.getClass(),targetClazz);
            if(joMapDefinition.getJoMapBase()!=null) {
                if (joMapDefinition.getReverseFlag()) {
                    return (T) joMapDefinition.getJoMapBase().copyBeanReverse(sourceObj);
                } else {
                    return (T) joMapDefinition.getJoMapBase().copyBean(sourceObj);
                }
            }else{
                return null;
            }
        }
    }

    /**
     * 列表实例属性赋值
     * @param sourceList
     * @param targetClazz
     * @param <K>
     * @return
     */
    public static <K,T> List<T> copyList(List<K> sourceList, Class<T> targetClazz){
        if(CollectUtil.isEmpty(sourceList)){
            return Collections.emptyList();
        }
        Class sourceClazz=sourceList.get(0).getClass();
        String sourceClazzName=sourceClazz.getSimpleName();
        String targetClazzName=targetClazz.getSimpleName();
        String convertClazzName=sourceClazzName.concat(Constant.CONVERT_JO_CHAR).concat(targetClazzName);
        String convertReverseClazzName=targetClazzName.concat(Constant.CONVERT_JO_CHAR).concat(sourceClazzName);
        JoMapBase joMapBase=convertClazzNameKeyJoBaseMap.get(convertClazzName);
        if(joMapBase!=null){
            return (List<T>) joMapBase.copyList(sourceList);
        }
        //反转
        joMapBase=convertClazzNameKeyJoBaseMap.get(convertReverseClazzName);
        if(joMapBase!=null){
            return (List<T>) joMapBase.copyListReverse(sourceList);
        }else{
            //缓存中不存在
            JoMapDefinition joMapDefinition=parseConvertInstant(sourceClazz,targetClazz);
            if(joMapDefinition.getJoMapBase()!=null) {
                if (joMapDefinition.getReverseFlag()) {
                    return (List<T>) joMapDefinition.getJoMapBase().copyListReverse(sourceList);
                } else {
                    return (List<T>) joMapDefinition.getJoMapBase().copyList(sourceList);
                }
            }else{
                return Collections.emptyList();
            }
        }
    }

    /**
     * 解析convert实例
     * @param sourceClazz  原Clazz
     * @param targetClazz  目标Clazz
     * @return
     */
    private static JoMapDefinition parseConvertInstant(Class sourceClazz,Class targetClazz){
        String sourceClazzName=sourceClazz.getSimpleName();
        String targetClazzName=targetClazz.getSimpleName();
        String convertClazzName=sourceClazzName.concat(Constant.CONVERT_JO_CHAR).concat(targetClazzName);
        String convertReverseClazzName=targetClazzName.concat(Constant.CONVERT_JO_CHAR).concat(sourceClazzName);
        //copyBean是否反转标记: true:调用copyBean, false:调用copyBeanReverse
        Boolean reverseFlag=Boolean.FALSE;
        JoMapBase joMapBase=null;
        //缓存中不存在--加载对应的convert类并缓存
        String convertClazzPath=Constant.JOMAP_PACKAGE.concat(Constant.DOT).concat(convertClazzName);
        Class convertClazz=null;
        String convertClazzKey=null;
        try {
            convertClazz=Thread.currentThread().getContextClassLoader().loadClass(convertClazzPath);
            convertClazzKey=convertClazzName;
        } catch (ClassNotFoundException e) {
            try {
                String convertReverseClazzPath=Constant.JOMAP_PACKAGE.concat(Constant.DOT).concat(convertReverseClazzName);
                convertClazz=Thread.currentThread().getContextClassLoader().loadClass(convertReverseClazzPath);
                reverseFlag=Boolean.TRUE;
                convertClazzKey=convertReverseClazzName;
            } catch (ClassNotFoundException e1) {
                e1.printStackTrace();
            }
        }
        if(convertClazz!=null) {
            try {
                Method method = convertClazz.getMethod("getInstance");
                Object instant=method.invoke(null);
                joMapBase=(JoMapBase) instant;
                //存入缓存
                convertClazzNameKeyJoBaseMap.put(convertClazzKey,joMapBase);
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }else{
            throw new RuntimeException("class dont load");
        }
        JoMapDefinition joMapDefinition=new JoMapDefinition();
        joMapDefinition.setReverseFlag(reverseFlag);
        joMapDefinition.setJoMapBase(joMapBase);
        return joMapDefinition;
    }
}
